﻿using AppInfo;
using BoardGame;
using GameModel;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Input;
using System.Reflection;


namespace WpfChess
{
    /// <summary>Interaction logic.</summary>
    public partial class ChessWpfController : Window
    {
        private ChessModel chessGame;

        public ChessWpfController ()
        {
            InitializeComponent ();
        }


        ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// 

        private Brush lightBrush = Brushes.Tan;
        private Brush darkBrush = Brushes.Brown;
        private Brush hiliteBrush = Brushes.Purple;


        private void CreateBoardWidget ()
        {
            for (int y = chessGame.Board.YSize - 1; y >= 0; --y)
                for (int x = 0; x < chessGame.Board.XSize; ++x)
                {
                    TextBlock tb1 = new TextBlock ();
                    tb1.Tag = boardGrid.Children.Count;
                    boardGrid.Children.Add (tb1);

                    tb1.MouseDown += square_MouseDown;
                    tb1.MouseRightButtonDown += square_MouseRightButtonDown;
                    tb1.MouseRightButtonUp += square_MouseRightButtonUp;
                    tb1.Background = BrushFromCoordinate (x, y);

                }
        }

        public Brush BrushFromCoordinate (int x, int y)
        { return (x + y) % 2 != 0 ? lightBrush : darkBrush; }


        public void ChangeHilite (int x, int y, bool newHilite)
        {
            TextBlock cell = (TextBlock) boardGrid.Children[(7 - y) * 8 + x];
            if (newHilite)
                cell.Background = hiliteBrush;
            else
                cell.Background = BrushFromCoordinate (x, y);
        }

        public void ClearHilites ()
        {
            ClearSelection ();

            for (int y = 0; y < 8; ++y)
                for (int x = 0; x < 8; ++x)
                {
                    TextBlock cell = (TextBlock) boardGrid.Children[(7 - y) * 8 + x];
                    cell.Background = BrushFromCoordinate (x, y);
                }
        }

        ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// 

        private bool hasSelection;
        public Coordinate Selection { get; private set; }

        public void ClearSelection ()
        {
            if (hasSelection)
            {
                hasSelection = false;
                ChangeHilite (Selection.X, Selection.Y, false);
            }
        }

        public void SetSelection (int newX, int newY)
        {
            if (hasSelection && Selection.X != newX && Selection.Y != newY)
                ClearSelection ();

            hasSelection = true;
            Selection = new Coordinate (newX, newY);
            ChangeHilite (newX, newY, true);
        }


        ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// 


        private void Window_Loaded (object sender, RoutedEventArgs e)
        {
            Assembly assembly = Assembly.GetExecutingAssembly ();
            Title = AppAbout.Title (assembly) + " " + AppAbout.Version (assembly);

            // Create the Model.
            chessGame = new ChessModel();

            // Create widgets that are dependent on the Model.
            CreateBoardWidget ();

            // Create the View and connect to the Model.
            ChessWpfView view = new ChessWpfView (this, chessGame);
        }

        /////

        private void fileMenuExit_Click (object sender, RoutedEventArgs e)
        {
            Close ();
        }

        static Coordinate CoordinateFromTag (FrameworkElement control)
        {
            int p = (int) control.Tag;
            int newY = p / 8;
            int newX = p - newY * 8;
            return new Coordinate (newX, 7 - newY);
        }

        private void square_MouseDown (object sender, MouseButtonEventArgs e)
        {
            if (!chessGame.IsUnderway)
                return;

            Coordinate place = CoordinateFromTag ((TextBlock) sender);

            if (e.ChangedButton == MouseButton.Left)
            {
                if (hasSelection)
                {
                    if (place.X == Selection.X && place.Y == Selection.Y)
                        ClearSelection ();
                    else
                        chessGame.MakeMove (Selection.X, Selection.Y, place.X, place.Y);
                }
                else if (chessGame.IsMovable (place.X, place.Y))
                    SetSelection (place.X, place.Y);
            }
        }

        private void square_MouseRightButtonDown (object sender, MouseButtonEventArgs e)
        {
            if (!chessGame.IsUnderway)
                return;

            Coordinate p = CoordinateFromTag ((FrameworkElement) sender);
            chessGame.BeginShowMoves (p.X, p.Y);
        }

        private void square_MouseRightButtonUp (object sender, MouseButtonEventArgs e)
        {
            chessGame.EndShowMoves ();
        }

        private void promoList_SelectionChanged (object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 1)
            {
                ListBoxItem item = e.AddedItems[0] as ListBoxItem;
                if (chessGame.CurrentPlayerPromotionName.CompareTo (item.Content.ToString ()) != 0)
                    chessGame.SetPromotion (item.Content.ToString ());
            }
        }

        ////////

        private void drawMenuRequest_Click (object sender, RoutedEventArgs e)
        {
            chessGame.DrawGame ();
        }

        private void drawMenuNoCaptures_Click (object sender, RoutedEventArgs e)
        {
            chessGame.DrawGame ();
        }

        private void drawMenuSame6_Click (object sender, RoutedEventArgs e)
        {
            chessGame.DrawGame ();
        }

        private void gameMenuNew_Click (object sender, RoutedEventArgs e)
        {
            chessGame.SetupStandard ();
        }

        private void gameMenuResign_Click (object sender, RoutedEventArgs e)
        {
            chessGame.ResignGame ();
        }

        private void gameMenuUndo_Click (object sender, RoutedEventArgs e)
        {
            chessGame.UndoMove ();
        }

        ////////

        private void helpMenuAbout_Click (object sender, RoutedEventArgs e)
        {
            Window dialog = new WpfAbout ();
            dialog.Owner = this;
            bool? result = dialog.ShowDialog ();
        }
    }
}
